package model;

import java.io.File;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;

import recipe.RecipeData;

import manager.FileManager;

import dlldynamicset.DLLDynamicSet;

/**
 * Class - DataManagerModel
 * Description - The data model for the viewcontrollers
 * @author Ryne Okimoto
 */
public class DataManagerModel {

	private static final String ROOT_DIRECTORY = "./rcp_db";
	private static final String RCP_DIRECTORY = ROOT_DIRECTORY + "/Rcp_Files";
	private static final String IMG_DIRECTORY = ROOT_DIRECTORY + "/Img_Files";
	
	private File rootDirectory;
	private File recipeDirectory;
	private File imageDirectory;
	private FileManager currentFileManager;
	private DirectoryStream<Path> recipeStream;
	
	private DLLDynamicSet<FileManager, String> recipeDataSet;
	
	private Iterator<FileManager> modelIterator;
	
	/**
	 * Constructor
	 */
	public DataManagerModel(){
		
		recipeDataSet = new DLLDynamicSet<FileManager, String>();
		currentFileManager = null;
		
		rootDirectory = new File(ROOT_DIRECTORY);
		recipeDirectory = new File(RCP_DIRECTORY);
		imageDirectory = new File(IMG_DIRECTORY);
		
		// Create file system only if it doesn't exist
		if(!checkDirectoryExistence()){
			rootDirectory.mkdir();
			recipeDirectory.mkdir();
			imageDirectory.mkdir();
		}
		
		try{
			recipeStream = Files.newDirectoryStream(Paths.get(RCP_DIRECTORY));
		}
		catch(IOException io){
			io.printStackTrace();
			io.getMessage();
		}
		
		readFileDirectory();
		modelIterator = recipeDataSet.iterator();
		
	} // constructor
	
	/**
	 * Method - readFileDirectory
	 * Description - Reads data from recipe directory 
	 * and loads into data set
	 * @return void
	 */
	private void readFileDirectory(){
		File tempFile = null;
		String fileName = null;
		
		for(Path file : recipeStream){
			tempFile = file.toFile();
			fileName = tempFile.getName();
			
			recipeDataSet.insertObject(new FileManager(fileName, tempFile), fileName);
		}
	}
	
	/**
	 * Method - checkDirectoryExistence
	 * Description - Verifies that recipe filesystem is created
	 * @return True - Returns if filesystem exists
	 * @return False - Returns if filesystem does not exist
	 */
	private boolean checkDirectoryExistence(){
		return Files.exists(Paths.get(ROOT_DIRECTORY)) && 
			   Files.exists(Paths.get(RCP_DIRECTORY)) &&
			   Files.exists(Paths.get(IMG_DIRECTORY));
	}
	
	/**
	 * Method - addFileManager
	 * Description - Adds a new FileManager
	 * @param recipeName
	 * @param category
	 * @param ingredients
	 * @param instructions
	 * @return True - Returns if addition succeeds
	 * @return False - Returns if addition fails
	 */
	public boolean addFileManager
		(String recipeName, String category, String ingredients, 
		String instructions, String tags, String image){

		boolean addIsSuccessful = false;
		
		// Create manager
		FileManager addManager = new FileManager(recipeName + ".rcp");
		addIsSuccessful = addManager.createRecipe(
				recipeName, category, ingredients, instructions, image, tags);
		
		// Add manager to collection
		if(addIsSuccessful){
			recipeDataSet.insertObject(addManager, recipeName);
		}
		
		return addIsSuccessful;
	}
	
	/**
	 * Method - setCurrentFileManager
	 * Description - Sets a reference to the current FileManager being used
	 * @param fm
	 * @return void
	 */
	public void setCurrentFileManager(FileManager fm){
		this.currentFileManager = fm;
	}
	
	/**
	 * Method - getCurrentFileManager
	 * Description - Gets the reference to the FileManager being used
	 * @return FileManager - the reference to the FileManager
	 */
	public FileManager getCurrentFileManager(){
		return currentFileManager;
	}
	
	/**
	 * Method - modifyFileManager
	 * Description - Changes the RecipeData object of the current FileManager
	 * @param recipeName
	 * @param category
	 * @param ingredients
	 * @param instructions
	 * @param tags
	 * @param image
	 * @return True - Returns if data is modified
	 * @return False - Returns if data is not modified
	 */
	public boolean modifyFileManager
		(String recipeName, String category, String ingredients, 
		String instructions, String tags, String image){
		
		boolean isModified = false;
		RecipeData tempData = currentFileManager.getData();
		
		// If recipe name changes, change filename
		if(!recipeName.equals(tempData.getRecipeName())){
			currentFileManager.resetFile(recipeName + ".rcp");
		}
		
		if(tempData != null){
			tempData.setRecipeName(recipeName);
			tempData.setCategory(category);
			tempData.setListOfIngredients(ingredients);
			tempData.setInstructions(instructions);
			tempData.setTags(tags);
			tempData.setImageFileName(image);
			
			isModified = true;
		}
		
		return isModified;
	}
	
	/**
	 * Unit tester
	 * @param args
	 */
	public static void main(String[] args){
		System.out.println(
				"*** DataManagerModel Unit Test ***\n\n" +
				"Creating DataManagerModel object and calling constructor...\n");
		
		DataManagerModel testModel = new DataManagerModel();
		
		System.out.println("Printing FileManagers...");
		while(testModel.modelIterator.hasNext()){
			System.out.println(testModel.modelIterator.next().createString());
		}
	} // main

} // DataManagerModel
